import initServer, { registerServerPlugins } from '@kuiper/core';
import readConfig from '@kuiper/core/dist/lib/readConfig';
import fetch from 'fermionjs/lib/fetch';

import modelsBuilder from './modelsBuilder';
import { TASK_TYPE_CATEGORY_MAP } from '../common/constants';
import config from '../config';

const { config: appConfig } = readConfig();

(async () => {
	const server = await initServer({ host: '127.0.0.1', port: '0' });

	server.app.config = appConfig;

	await registerServerPlugins({
		server,
		plugins: [
			'@kuiper/mongo',
			'@kuiper/graphql',
			'@kuiper/react-base',
			'@kuiper/auth',
		],
	});

	modelsBuilder(server);
	await server.start();

	const {
		Asset,
		User,
		Job,
		Task,
		Alert,
		NotificationSendLog,
		AlertGroup,
		ResultNumbers,
	} = server.app.model;
	const user = await User.findOne({ type: 'cas' });
	const alertGroup = await AlertGroup.findOne({
		uid: user.id,
		isDefault: true,
	});

	const assetTask = new Task({
		alertSettings: {
			alertGroupIds: [alertGroup.id],
		},
		taskSettings: {
			interval: {
				num: 10,
				unit: 'day',
			},
			enable: true,
			target: 'knownsec.ml',
			collect: {
				ipBindDomain: true,
			},
			alert: {
				subdomain: true,
				port: true,
			},
		},
		result: {
			warnings: [
				{
					id: 'asset\x01\x02domain',
					category: 'domain',
					level: 1,
					affects: 'www1.knownsec.ml',
					title: '[knownsec.ml]监测到新子域名',
					ignoredTime: null,
					isResolved: false,
					detail: {
						affects: 'www1.knownsec.ml',
					},
				},
				{
					id: 'asset\x01\x02port',
					category: 'port',
					level: 1,
					affects: 'www.knownsec.ml(127.0.0.1) -- 80(HTTP)',
					title: '[knownsec.ml]监测到端口/服务',
					ignoredTime: null,
					isResolved: false,
					detail: {
						affects: 'www.knownsec.ml(127.0.0.1) -- 80(HTTP)',
					},
				},
				{
					id: 'asset\x01\x02port',
					category: 'port',
					level: 1,
					affects: 'www.knownsec.ml(127.0.0.1) -- 25(SMTP)',
					title: '[knownsec.ml]监测到端口/服务',
					ignoredTime: null,
					isResolved: false,
					detail: {
						affects: 'www.knownsec.ml(127.0.0.1) -- 25(SMTP)',
					},
				},
				{
					id: 'asset\x01\x02port',
					category: 'port',
					level: 1,
					affects: 'www.knownsec.ml(127.0.0.1) -- 8443(HTTP)',
					title: '[knownsec.ml]监测到端口/服务',
					ignoredTime: null,
					isResolved: false,
				},
			],
			subDomains: [
				{
					host: 'gac.knownsec.ml',
					point: '10.255.11.240',
				},
				{
					host: 'knownsec.ml',
					point: '10.255.11.240',
				},
				{
					host: 'www.knownsec.ml',
					point: '10.255.11.240',
				},
				{
					host: 'ss.knownsec.ml',
					point: '45.14.66.22',
				},
				{
					host: 'dev-gac.knownsec.ml',
					point: '10.255.11.240',
				},
				{
					host: 'go2world.knownsec.ml',
					point: '107.172.2.142',
				},
			],
			ipPorts: [
				{
					ip: '107.172.2.142',
					hostname: 'LiDAR-x1',
					location: '洛杉矶 加利福尼亚州 , 美国',
					ports: [
						{
							reason: 'no-response',
							port: 111,
							service: 'rpcbind',
							proto: 'udp',
						},
						{
							reason: 'no-response',
							port: 123,
							service: 'ntp',
							proto: 'udp',
						},
						{
							reason: 'no-response',
							port: 407,
							service: 'timbuktu',
							proto: 'udp',
						},
						{
							reason: 'udp-response',
							port: 500,
							service: 'isakmp',
							proto: 'udp',
						},
						{
							reason: 'no-response',
							port: 1900,
							service: 'upnp',
							proto: 'udp',
						},
						{
							reason: 'no-response',
							port: 11211,
							service: 'memcache',
							proto: 'udp',
						},
					],
				},
			],
			ipBindDomains: [
				{
					ip: '107.172.2.142',
					domains: [
						{ domain: 'www.example.com', title: 'wordpress' },
						{ domain: 'forum.example.com', title: 'discuz' },
					],
				},
				{
					ip: '10.255.11.240',
					domains: [
						{ domain: 'quick.example.com', title: 'quick links' },
						{ domain: 'printer.example.com', title: 'hp printer' },
					],
				},
			],
			warningCount: 4,
		},
		isSpecialTask: false,
		securityStatus: 'warning',
		status: 'completed',
		progress: 100,
		triggerType: 'schedule',
		isLatestTask: true,
		uid: user.id,
		domain: 'knownsec.m',
		target: 'knownsec.ml',
		refType: 'asset',
		taskType: 'asset',
		startTime: new Date('2020-06-08T03:59:02.912Z'),
		endTime: new Date('2020-06-08T03:59:04.597Z'),
	});

	const asset = new Asset({
		taskSettings: {
			interval: {
				num: 10,
				unit: 'day',
			},
			enable: true,
			target: 'knownsec.ml',
			collect: {
				ipBindDomain: true,
			},
			alert: {
				subdomain: true,
				port: true,
			},
		},
		alertSettings: {
			notification: {
				email: true,
				sms: false,
				wechat: false,
			},
			enable: true,
			alertGroupIds: [alertGroup.id],
		},
		uid: user.id,
		target: 'knownsec.ml',
		targetType: 'domain',
		createTime: new Date(),
		customSubdomains: [],
		taskId: assetTask.id,
		resultId: assetTask.id,
	});

	assetTask.refId = asset.id;
	const job = new Job({
		...config.defaultJobSettings,
		target: {
			protocol: 'https:',
			host: 'gac.knownsec.ml',
			hostname: 'gac.knownsec.ml',
			ipType: 0,
			eTLD1: 'knownsec.ml',
		},
		verification: {
			isVerified: true,
			challenge: '5eddb93d33d2f64e9a32bb39',
			verifyType: 'backend',
		},
		assetId: asset.id,
		uid: user.id,
	});
	job.httpSettings[0].target = 'https://gac.knownsec.ml';
	job.httpSettings[0].name = '首页';
	job.pingSettings[0].target = 'gac.knownsec.ml';
	job.pingSettings[0].name = 'gac';
	job.sslSettings.enable = true;
	job.alertSettings.alertGroupIds = [alertGroup.id];
	asset.jobId = job._id;

	const sslTask = new Task({
		alertSettings: job.alertSettings,
		taskSettings: {
			interval: {
				num: 30,
				unit: 'day',
			},
			enable: true,
			alert: {
				enable: true,
			},
		},
		result: {
			warnings: [
				{
					id: 'ssl\u0001\u0002Drown',
					level: 2,
					title: 'OpenSSL跨协议攻击漏洞',
					category: '漏洞',
					affects: 'http://gac.knownsec.ml/',
					ignoredTime: null,
					isResolved: false,
					detail: {
						risk: '中',
						affects: 'http://gac.knownsec.ml/',
						recommendation: '升级OpenSSL。',
						display_name: 'OpenSSL跨协议攻击漏洞',
						detail: '',
						impact:
							'攻击者可利用该漏洞通过DROWN攻击方式破解采用TLS协议加密的会话数据。',
						description:
							'OpenSSL 1.0.2及更早版本、1.0.1及更早版本存在跨协议攻击漏洞，用支持SSLv2及EXPORT加密组件的服务器作为Bleichenbacher RSA padding Oracle攻击方式，可进行TLS会话解密。如果支持的SSLv2及EXPORT加密组件的服务器共享了不受影响服务器的RSA密钥，则客户端及不受影响服务器之间的流量也可被解密。此漏洞被称为DROWN。',
						cve: 'CVE-2016-0800',
					},
				},
				{
					id: 'ssl\u0001\u0002Freak',
					level: 2,
					title: 'OpenSSL FREAK Attack漏洞',
					category: '漏洞',
					affects: 'http://gac.knownsec.ml/',
					ignoredTime: null,
					isResolved: false,
					detail: {
						risk: '中',
						affects: 'http://gac.knownsec.ml/',
						recommendation: '升级OpenSSL。',
						display_name: 'OpenSSL FREAK Attack漏洞',
						detail: '',
						impact: '攻击者可进行暴力破解，得到服务端秘钥。',
						description:
							'该漏洞是由于OpenSSL库里的s3_clnt.c文件中，ssl3_get_key_exchange函数，允许客户端使用一个弱RSA秘钥，向SSL服务端发起RSA-to-EXPORT_RSA的降级攻击，以此进行暴力破解，得到服务端秘钥。',
						cve: 'CVE-2015-0204',
					},
				},
				{
					id: 'ssl\u0001\u0002Logjam',
					level: 2,
					title: 'SSL/TLS LogJam中间人安全限制绕过漏洞',
					category: '漏洞',
					affects: 'http://gac.knownsec.ml/',
					ignoredTime: null,
					isResolved: false,
					detail: {
						risk: '中',
						affects: 'http://gac.knownsec.ml/',
						recommendation: '升级OpenSSL。',
						display_name: 'SSL/TLS LogJam中间人安全限制绕过漏洞',
						detail: '',
						impact: '攻击者可利用此漏洞可执行密码降级攻击。',
						description:
							'TLS 1.2及更早版本，在服务器上启用但不在客户端启用DHE_EXPORT密码组时，没有正确转送DHE_EXPORT选择，中间人攻击者通过用DHE_EXPORT代替DHE，重写ClientHello，然后用DHE代替DHE_EXPORT，重写ServerHello(即"Logjam"问题)，利用此漏洞可执行密码降级攻击。',
						cve: 'CVE-2015-4000',
					},
				},
			],
			warningCount: 3,
		},
		isSpecialTask: false,
		securityStatus: 'warning',
		status: 'completed',
		progress: 100,
		triggerType: 'schedule',
		isLatestTask: true,
		uid: user.id,
		domain: 'gac.knownsec.ml',
		target: 'gac.knownsec.ml',
		taskType: 'ssl',
		refType: 'job',
		refId: job.id,
		startTime: new Date('2020-06-07T10:51:25.735Z'),
		taskId: '2',
		endTime: new Date('2020-06-07T09:11:16.152Z'),
	});
	const sslTaskResultNumbers = new ResultNumbers({
		taskType: sslTask.taskType,
		uid: sslTask.uid,
		jobId: job._id,
		taskName: sslTask.name,
		target: sslTask.target,
		datetime: sslTask.endTime,
		taskId: sslTask._id,
		highWarnCount: 0,
		mediumWarnCount: 3,
		lowWarnCount: 0,
		warnCount: 3,
		aviliable: [],
	});
	const sslTaskRunning = new Task({
		alertSettings: job.alertSettings,
		taskSettings: {
			interval: {
				num: 30,
				unit: 'day',
			},
			enable: true,
			alert: {
				enable: true,
			},
		},
		isSpecialTask: false,
		securityStatus: 'unknown',
		status: 'active',
		progress: 10,
		triggerType: 'schedule',
		isLatestTask: true,
		uid: user.id,
		domain: 'gac.knownsec.ml',
		target: 'gac.knownsec.ml',
		taskType: 'ssl',
		refType: 'job',
		refId: job.id,
		startTime: new Date('2020-06-08T10:51:25.735Z'),
		taskId: '2',
	});
	job.sslStatustId = sslTaskRunning.id;
	job.sslResultId = sslTask.id;

	const vulTask = new Task({
		alertSettings: job.alertSettings,
		taskSettings: {
			interval: {
				num: 7,
				unit: 'day',
			},
			enable: true,
			collect: {
				type: 'full',
				status: true,
				speed: 'high',
				depth: 3,
				maxPage: 1000,
			},
			alert: {
				vulLevel: {
					high: true,
					medium: true,
					low: false,
				},
				vulType: ['webvul', 'command_execution', 'injection'],
			},
		},
		result: {
			addition: {
				statistics: {
					files: 16,
					exact_file_type: {
						xml: [
							'http://gac.knownsec.ml:80/sitemap.xml',
							'https://gac.knownsec.ml:443/sitemap.xml',
						],
						txt: [
							'http://gac.knownsec.ml:80/robots.txt',
							'https://gac.knownsec.ml:443/robots.txt',
						],
					},
					waf: [],
					filetype: {
						xml: 2,
						txt: 2,
					},
					siteattrs: {
						dbms: [],
						os_path: [],
						hardware: [],
						webserver: [
							{
								version: ['1.14.2'],
								name: ['Nginx'],
							},
						],
						vcs: [],
						tech: [],
						os: [],
					},
					forms: {
						forms: [],
						hidden_param: [],
					},
					urls: 16,
					broken_links: [
						['https://gac.knownsec.ml/robots.txt', null],
						['https://gac.knownsec.ml/old', null],
						['https://gac.knownsec.ml/back', null],
						['https://gac.knownsec.ml/sitemap.xml', null],
						['https://gac.knownsec.ml/admin', null],
						['https://gac.knownsec.ml/bak', null],
						['https://gac.knownsec.ml/Manager', null],
					],
					wmap: {
						framework: [],
						webapp: [],
						plugin: [],
					},
				},
				info: {},
			},
			warnings: [
				{
					isResolved: false,
					id: 'vul\u0001\u0002clickjacking_x_frame_options',
					level: 1,
					title: 'X-Frame-Options Header未配置',
					category: '配置风险',
					affects: 'http://gac.knownsec.ml/',
					detail: {
						postdata: null,
						report_type: 'uri',
						recommendation:
							"配置Web服务器，添加一个 'X-Frame-Options' 响应头部字段",
						payload: null,
						risk: '低',
						category: '配置风险',
						update_date: '20160107',
						display_name: 'X-Frame-Options Header未配置',
						reference: [
							'https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet#Defending_with_Content_Security_Policy_frame-ancestors_directive',
						],
						affects: 'http://gac.knownsec.ml/',
						detail: '发现防止点击劫持的http头部 `X-Frame-Options` 缺失',
						from_type: 'plugin',
						ssvid: null,
						cnnvd: null,
						parameter: null,
						impact: '风险取决于受影响的Web应用程序。',
						description:
							'点击劫持（用户界面伪装攻击，UI伪装攻击）是引诱网络用户点击界面看不到的链接或操作，从而有可能泄露机密信息或操作看似无害的网页，而实际执行恶意操作。',
						tags: '配置风险',
						cnvd: null,
						bid: null,
						extra_detail: null,
						parameter_value: null,
						name: 'clickjacking_x_frame_options',
						url: 'http://gac.knownsec.ml/',
						cwe: null,
						release_date: '20080307',
						httpmethod: 'GET',
						place: null,
						cve: null,
					},
				},
			],
			warningCount: 1,
			ipBindDomains: [],
			ipPorts: [],
			subDomains: [],
		},
		isSpecialTask: false,
		securityStatus: 'warning',
		status: 'stopped',
		progress: 1,
		triggerType: 'schedule',
		isLatestTask: true,
		uid: user.id,
		domain: 'gac.knownsec.ml',
		target: 'gac.knownsec.ml',
		taskType: 'vul',
		refType: 'job',
		refId: job.id,
		startTime: new Date('2020-06-08T16:00:46.225Z'),
		taskId: '4',
		endTime: new Date('2020-06-10T09:11:16.169Z'),
	});
	const vulTaskResultNumbers = new ResultNumbers({
		taskType: vulTask.taskType,
		uid: vulTask.uid,
		jobId: job._id,
		taskName: vulTask.name,
		target: vulTask.target,
		datetime: vulTask.endTime,
		taskId: vulTask._id,
		highWarnCount: 0,
		mediumWarnCount: 0,
		lowWarnCount: 1,
		warnCount: 1,
		aviliable: [],
	});
	const vulTaskRunning = new Task({
		alertSettings: job.alertSettings,
		taskSettings: {
			interval: {
				num: 7,
				unit: 'day',
			},
			enable: true,
			collect: {
				type: 'full',
				status: true,
				speed: 'high',
				depth: 3,
				maxPage: 1000,
			},
			alert: {
				vulLevel: {
					high: true,
					medium: true,
					low: false,
				},
				vulType: ['webvul', 'command_execution', 'injection'],
			},
		},
		isSpecialTask: false,
		status: 'active',
		progress: 10,
		triggerType: 'manual',
		isLatestTask: true,
		uid: user.id,
		domain: 'gac.knownsec.ml',
		target: 'gac.knownsec.ml',
		taskType: 'vul',
		refType: 'job',
		refId: job.id,
		startTime: new Date('2020-06-10T16:00:46.225Z'),
		taskId: '7',
	});
	const vulTaskSpecialRunning = new Task({
		alertSettings: job.alertSettings,
		taskSettings: {
			interval: {
				num: 7,
				unit: 'day',
			},
			enable: true,
			collect: {
				type: 'full',
				status: true,
				speed: 'high',
				depth: 3,
				maxPage: 1000,
			},
			alert: {
				vulLevel: {
					high: true,
					medium: true,
					low: false,
				},
				vulType: ['webvul', 'command_execution', 'injection'],
			},
		},
		isSpecialTask: true,
		status: 'active',
		progress: 20,
		triggerType: 'manual',
		uid: user.id,
		domain: 'gac.knownsec.ml',
		target: 'gac.knownsec.ml',
		taskType: 'vul',
		refType: 'job',
		refId: job.id,
		startTime: new Date('2020-06-10T16:00:46.225Z'),
		taskId: '8',
	});
	job.vulStatustId = vulTaskRunning.id;
	job.vulResultId = vulTask.id;

	console.log('save');
	await Promise.all([
		assetTask.save(),
		asset.save(),
		job.save(),
		sslTask.save(),
		sslTaskRunning.save(),
		sslTaskResultNumbers.save(),
		vulTask.save(),
		vulTaskRunning.save(),
		vulTaskSpecialRunning.save(),
		vulTaskResultNumbers.save(),

		new NotificationSendLog({
			uid: user._id,
			refId: vulTask._id,
			domain: vulTask.target,
			status: ['pending', 'success', 'fail'][Math.round(Math.random() * 3)],
			taskCategory: 'weakness',
			taskType: vulTask.taskType,
			target: vulTask.target,
			startTime: vulTask.startTime,
			endTime: vulTask.endTime,
			title: `[${vulTask.target}]敏感文件泄露`,
			summary: '备份文件没有限制访问权限：/backup.zip',
			content: '备份文件没有限制访问权限：<b>/backup.zip</b>',
			receivers: [{ type: 'email', contact: 'admin@example.com' }],
		}).save(),
		new NotificationSendLog({
			uid: user._id,
			refId: vulTask._id,
			domain: vulTask.target,
			status: ['pending', 'success', 'fail'][Math.round(Math.random() * 3)],
			taskCategory: 'weakness',
			taskType: vulTask.taskType,
			target: vulTask.target,
			startTime: vulTask.startTime,
			endTime: vulTask.endTime,
			title: `[${vulTask.target}]敏感文件泄露`,
			summary: '备份文件没有限制访问权限：/backup.zip',
			content: '备份文件没有限制访问权限：<b>/backup.zip</b>',
			receivers: [{ type: 'email', contact: 'admin@example.com' }],
		}).save(),
		new NotificationSendLog({
			uid: user._id,
			refId: vulTask._id,
			domain: vulTask.target,
			status: ['pending', 'success', 'fail'][Math.round(Math.random() * 3)],
			taskCategory: 'weakness',
			taskType: vulTask.taskType,
			target: vulTask.target,
			startTime: vulTask.startTime,
			endTime: vulTask.endTime,
			title: `[${vulTask.target}]敏感文件泄露`,
			summary: '备份文件没有限制访问权限：/backup.zip',
			content: '备份文件没有限制访问权限：<b>/backup.zip</b>',
			receivers: [{ type: 'email', contact: 'admin@example.com' }],
		}).save(),

		new Alert({
			domain: assetTask.target,
			target: assetTask.target,
			taskId: assetTask._id,
			taskType: assetTask.taskType,
			taskTriggerType: assetTask.triggerType,
			securityStatus: assetTask.securityStatus,
			title: '[example.com]监测到新端口/服务',
			summary: '80(Nginx)\n25(SMTP)',
			content: '<div>80(Nginx)</div><div>25(SMTP)</div>',
			detail: '',
			taskCategory: TASK_TYPE_CATEGORY_MAP[assetTask.taskType],
			alertType: 'abnormal',
			taskName: assetTask.name,
			uid: assetTask.uid,
			duration: 0,
		}).save(),
		new Alert({
			domain: assetTask.target,
			target: assetTask.target,
			taskId: assetTask._id,
			taskType: assetTask.taskType,
			taskTriggerType: assetTask.triggerType,
			securityStatus: assetTask.securityStatus,
			title: '[example.com]监测到新子域名',
			summary: 'www1.example.com',
			content: '<div>www1.example.com</div>',
			detail: '',
			taskCategory: TASK_TYPE_CATEGORY_MAP[assetTask.taskType],
			alertType: 'abnormal',
			taskName: assetTask.name,
			uid: assetTask.uid,
			duration: 0,
		}).save(),
		new Alert({
			domain: assetTask.target,
			target: assetTask.target,
			taskId: assetTask._id,
			taskType: assetTask.taskType,
			taskTriggerType: assetTask.triggerType,
			securityStatus: assetTask.securityStatus,
			title: '[example.com]监测到新IP',
			summary: '127.0.0.1',
			content: '<div>127.0.0.1</div>',
			detail: '',
			taskCategory: TASK_TYPE_CATEGORY_MAP[assetTask.taskType],
			alertType: 'abnormal',
			taskName: assetTask.name,
			uid: assetTask.uid,
			duration: 0,
		}).save(),
	]).catch(error => console.log(error));

	/**
	 * 初始化网站画像
	 */
	const token = appConfig['@kuiper/graphql'].devToken;
	await fetch(
		`http://127.0.0.1:8000/api/v1/site-portrait/${job.target.hostname}?token=${token}`,
		{
			method: 'PUT',
			body: JSON.stringify({
				parameter_names: [],
				child: {
					'index.php': {
						parameter_names: [],
						child: {},
					},
					page: {
						parameter_names: [],
						child: {
							'about.php': {
								child: {},
							},
						},
					},
				},
			}),
		}
	).catch(error => {
		console.log(error);
		process.exit(1);
	});
	await fetch(
		`http://127.0.0.1:8000/api/v1/site-portrait/${job.target.hostname}?token=${token}`,
		{
			method: 'PUT',
			body: JSON.stringify({
				parameter_names: [],
				child: {
					'index.php': {
						parameter_names: [],
						child: {},
					},
					page: {
						parameter_names: [],
						child: {
							'about.php': {
								child: {},
							},
							'product.php': {
								child: {},
							},
							'search.php': {
								child: {},
							},
						},
					},
				},
			}),
		}
	).catch(error => {
		console.log(error);
		process.exit(1);
	});
	await fetch(
		`http://127.0.0.1:8000/api/v1/site-portrait/${job.target.hostname}?token=${token}`,
		{
			method: 'PUT',
			body: JSON.stringify({
				parameter_names: [],
				child: {
					'index.php': {
						parameter_names: [],
						child: {},
					},
					page: {
						parameter_names: [],
						child: {
							'about.php': {
								child: {},
							},
							'product.php': {
								child: {},
							},
							'search.php': {
								child: {},
							},
							'profile.php': {
								child: {},
							},
						},
					},
				},
			}),
		}
	).catch(error => {
		console.log(error);
		process.exit(1);
	});

	process.exit();
})();
